package utils
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;

	/**
	 * 数字工具类,还有位操作
	 * @author WynnLam
	 * 
	 */	
	public class NumericUtil
	{
		//16进制字符表
		public static const HexCharTable: Array = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
		
		/**
		 * 整数转换为16进制字符串
		 * 返回格式为"FFFFFFFF"的字符串，并不带有"0x"或"H"
		 * @param N
		 * @return 
		 * 
		 */
		public static function IntToHex(N: uint): String
		{
			return HexCharTable[(N & 0xF0000000) >> 28]
			+ HexCharTable[(N & 0x0F000000) >> 24]
				+ HexCharTable[(N & 0x00F00000) >> 20]
				+ HexCharTable[(N & 0x000F0000) >> 16]
				+ HexCharTable[(N & 0x0000F000) >> 12]
				+ HexCharTable[(N & 0x00000F00) >> 8]
				+ HexCharTable[(N & 0x000000F0) >> 4]
				+ HexCharTable[N & 0x0000000F];
		}
		/**
		 * 16进制字符串转换为整数 
		 * @param S 格式为"FFFFFFFF"的字符串，并不带有"0x"或"H"
		 * @return 
		 * 
		 */
		public static function HexToInt(S: String): uint
		{
			var Result: int = 0;
			var i: int, c: int;
			for ( i=0; i<8; ++i )
			{
				if ( i >= S.length )
					break;
				Result <<= 4;
				c = S.charCodeAt(i);
				if ( c >= 0x30 && c <= 0x39 )
					Result |= c - 0x30;
				else if ( c >= 0x41 && c <= 0x46 )
					Result |= (c - 0x41) + 10;
				else if ( c >= 0x61 && c <= 0x66 )
					Result |= (c - 0x61) + 10;
				else break;
			}
			return Result;
		}
		/**
		 * 将两个32位数据组合成一个64位数据
		 * 因为AS3最大的表示范围就是Number的53位
		 * 所以合并后的数值不能大于Number可以表示的范围
		 * 另外，这里不能使用移位操作，因为AS3的位操作都会把
		 * 数值转换成32位无符号整数
		 * @param lo
		 * @param hi
		 * @return 
		 * 
		 */		
		public static function MakeLong64(lo:uint, hi:uint):Number
		{
			var ret:Number = lo + hi * 0x100000000;
			return ret;
		}
		/**
		 * 将两个16位数据组合为一个32位数据 
		 * @param lo 低位
		 * @param hi 高位
		 * @return 
		 * 
		 */
		public static function MakeLong(lo: int, hi: int): uint
		{
			return (lo & 0xFFFF) | ((hi << 16) & 0xFFFF0000);
		}
		/**
		 * 将两个8位数据组合为一个16位数据 
		 * @param lo 低位
		 * @param hi 高位
		 * @return 
		 * 
		 */
		public static function MakeWord(lo: int, hi: int): uint
		{
			return (lo & 0xFF) | ((hi << 8) & 0xFF00);
		}
		/**
		 * 取一个32位整数的低16位 
		 * @param u
		 * @return 
		 * 
		 */
		public static function LoWord(u: uint): int
		{
			return u & 0xFFFF;
		}
		/**
		 * 取一个32位整数的高16位 
		 * @param u
		 * @return 
		 * 
		 */
		public static function HiWord(u: uint): int
		{
			return (u >> 16) & 0xFFFF;
		}
		/**
		 * 取一个16位整数的低8位 
		 * @param u
		 * @return 
		 * 
		 */
		public static function LoByte(u: uint): int
		{
			return u & 0xFF;
		}
		/**
		 * 取一个16位整数的高8位 
		 * @param u
		 * @return 
		 * 
		 */
		public static function HiByte(u: uint): int
		{
			return (u >> 8) & 0xFF;
		}
		/**
		 * 把一组数值按位合成一个32位整数
		 * @param bits
		 * @param endian
		 * @return 
		 * 
		 */		
		public static function MakeLongByBits(bits:Vector.<uint>, endian:String=null):int
		{
			var b:int = bits.length;
			if(b >= 32)
				throw new RangeError("按位保存值时位数超出范围：" + b);
			var i:int;
			var value:int = 0;
			if(endian == Endian.BIG_ENDIAN)
			{
				for(i=0; i<b; i++)
					value |= (bits[i] & 0x1) << (31 - i);
			}
			//默认使用低位优先
			else
			{
				for(i=0; i<b; i++)
					value |= (bits[i] & 0x1) << i;
			}
			return value;
		}
		/**
		 * 按百分比显示
		 * @param num
		 * @param fixed 小数位数
		 * @return 
		 * 
		 */		
		public static function PercentToFixed(num:Number, fixed:uint=2):String
		{
			return (num * 100).toFixed(fixed) + "%";
		}
		/**
		 * double转16禁止字符串
		 * @param val
		 * @return 
		 * 
		 */
		static private var d2hBytes: ByteArray;
		public static function DoubleToHex(val: Number): String
		{
			if (!d2hBytes)
			{
				d2hBytes = new ByteArray();
				d2hBytes.endian = Endian.LITTLE_ENDIAN;
			}
			d2hBytes.position = 0;
			d2hBytes.writeDouble(val);
			d2hBytes.position = 0;
			var lo: uint = d2hBytes.readUnsignedInt();
			var hi: uint = d2hBytes.readUnsignedInt();
			return hi.toString(16) + lo.toString(16);
		}
	}
}